﻿using System;
using System.Diagnostics;
using System.Net;
using System.Net.Sockets;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using HslCommunication.Core.IMessage;
using HslCommunication.LogNet;

namespace HslCommunication.Core.Net
{
	/// <summary>
	/// 服务器程序的基础类，提供了启动服务器的基本实现，方便后续的扩展操作。<br />
	/// The basic class of the server program provides the basic implementation of starting the server to facilitate subsequent expansion operations.
	/// </summary>
	// Token: 0x0200013E RID: 318
	public class NetworkServerBase : NetworkXBase
	{
		/// <summary>
		/// 实例化一个默认的对象<br />
		/// Instantiate a default object
		/// </summary>
		// Token: 0x06001B94 RID: 7060 RVA: 0x00089194 File Offset: 0x00087394
		public NetworkServerBase()
		{
			this.IsStarted = false;
			this.Port = 0;
		}

		/// <summary>
		/// 服务器引擎是否启动<br />
		/// Whether the server engine is started
		/// </summary>
		// Token: 0x17000578 RID: 1400
		// (get) Token: 0x06001B95 RID: 7061 RVA: 0x000891AE File Offset: 0x000873AE
		// (set) Token: 0x06001B96 RID: 7062 RVA: 0x000891B6 File Offset: 0x000873B6
		public bool IsStarted { get; protected set; }

		/// <summary>
		/// 获取或设置服务器的端口号，如果是设置，需要在服务器启动前设置完成，才能生效。<br />
		/// Gets or sets the port number of the server. If it is set, it needs to be set before the server starts to take effect.
		/// </summary>
		/// <remarks>需要在服务器启动之前设置为有效</remarks>
		// Token: 0x17000579 RID: 1401
		// (get) Token: 0x06001B97 RID: 7063 RVA: 0x000891BF File Offset: 0x000873BF
		// (set) Token: 0x06001B98 RID: 7064 RVA: 0x000891C7 File Offset: 0x000873C7
		public int Port { get; set; }

		/// <summary>
		/// 异步传入的连接申请请求<br />
		/// Asynchronous incoming connection request
		/// </summary>
		/// <param name="iar">异步对象</param>
		// Token: 0x06001B99 RID: 7065 RVA: 0x000891D0 File Offset: 0x000873D0
		protected void AsyncAcceptCallback(IAsyncResult iar)
		{
			Socket socket = iar.AsyncState as Socket;
			bool flag = socket != null;
			if (flag)
			{
				Socket socket2 = null;
				try
				{
					socket2 = socket.EndAccept(iar);
					ThreadPool.QueueUserWorkItem(new WaitCallback(this.ThreadPoolLogin), socket2);
				}
				catch (ObjectDisposedException)
				{
					return;
				}
				catch (Exception ex)
				{
					if (socket2 != null)
					{
						socket2.Close();
					}
					ILogNet logNet = base.LogNet;
					if (logNet != null)
					{
						logNet.WriteException(this.ToString(), StringResources.Language.SocketAcceptCallbackException, ex);
					}
				}
				int i = 0;
				while (i < 3)
				{
					try
					{
						socket.BeginAccept(new AsyncCallback(this.AsyncAcceptCallback), socket);
						break;
					}
					catch (Exception ex2)
					{
						Thread.Sleep(1000);
						ILogNet logNet2 = base.LogNet;
						if (logNet2 != null)
						{
							logNet2.WriteException(this.ToString(), StringResources.Language.SocketReAcceptCallbackException, ex2);
						}
						i++;
					}
				}
				bool flag2 = i >= 3;
				if (flag2)
				{
					ILogNet logNet3 = base.LogNet;
					if (logNet3 != null)
					{
						logNet3.WriteError(this.ToString(), StringResources.Language.SocketReAcceptCallbackException);
					}
					throw new Exception(StringResources.Language.SocketReAcceptCallbackException);
				}
			}
		}

		// Token: 0x06001B9A RID: 7066 RVA: 0x00089320 File Offset: 0x00087520
		private void ThreadPoolLogin(object obj)
		{
			Socket socket = obj as Socket;
			bool flag = socket != null;
			if (flag)
			{
				IPEndPoint ipendPoint = (IPEndPoint)socket.RemoteEndPoint;
				OperateResult operateResult = this.SocketAcceptExtraCheck(socket, ipendPoint);
				bool flag2 = !operateResult.IsSuccess;
				if (flag2)
				{
					ILogNet logNet = base.LogNet;
					if (logNet != null)
					{
						logNet.WriteDebug(this.ToString(), string.Format("[{0}] Socket Accept Extra Check Failed : {1}", ipendPoint, operateResult.Message));
					}
					if (socket != null)
					{
						socket.Close();
					}
				}
				else
				{
					this.ThreadPoolLogin(socket, ipendPoint);
				}
			}
		}

		/// <summary>
		/// 当客户端连接到服务器，并听过额外的检查后，进行回调的方法<br />
		/// Callback method when the client connects to the server and has heard additional checks
		/// </summary>
		/// <param name="socket">socket对象</param>
		/// <param name="endPoint">远程的终结点</param>
		// Token: 0x06001B9B RID: 7067 RVA: 0x000893A7 File Offset: 0x000875A7
		protected virtual void ThreadPoolLogin(Socket socket, IPEndPoint endPoint)
		{
			if (socket != null)
			{
				socket.Close();
			}
		}

		/// <summary>
		/// 当客户端的socket登录的时候额外检查的操作，并返回操作的结果信息。<br />
		/// The operation is additionally checked when the client's socket logs in, and the result information of the operation is returned.
		/// </summary>
		/// <param name="socket">套接字</param>
		/// <param name="endPoint">终结点</param>
		/// <returns>验证的结果</returns>
		// Token: 0x06001B9C RID: 7068 RVA: 0x0000A76D File Offset: 0x0000896D
		protected virtual OperateResult SocketAcceptExtraCheck(Socket socket, IPEndPoint endPoint)
		{
			return OperateResult.CreateSuccessResult();
		}

		/// <summary>
		/// 服务器启动时额外的初始化信息，可以用于启动一些额外的服务的操作。<br />
		/// The extra initialization information when the server starts can be used to start some additional service operations.
		/// </summary>
		/// <remarks>需要在派生类中重写</remarks>
		// Token: 0x06001B9D RID: 7069 RVA: 0x00009AA1 File Offset: 0x00007CA1
		protected virtual void StartInitialization()
		{
		}

		/// <summary>
		/// 指定端口号来启动服务器的引擎<br />
		/// Specify the port number to start the server's engine
		/// </summary>
		/// <param name="port">指定一个端口号</param>
		// Token: 0x06001B9E RID: 7070 RVA: 0x000893B8 File Offset: 0x000875B8
		public virtual void ServerStart(int port)
		{
			bool flag = !this.IsStarted;
			if (flag)
			{
				this.StartInitialization();
				this.CoreSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
				this.CoreSocket.Bind(new IPEndPoint(IPAddress.Any, port));
				this.CoreSocket.Listen(500);
				this.CoreSocket.BeginAccept(new AsyncCallback(this.AsyncAcceptCallback), this.CoreSocket);
				this.IsStarted = true;
				this.Port = port;
				ILogNet logNet = base.LogNet;
				if (logNet != null)
				{
					logNet.WriteInfo(this.ToString(), StringResources.Language.NetEngineStart);
				}
			}
		}

		/// <summary>
		/// 使用已经配置好的端口启动服务器的引擎<br />
		/// Use the configured port to start the server's engine
		/// </summary>
		// Token: 0x06001B9F RID: 7071 RVA: 0x00089465 File Offset: 0x00087665
		public void ServerStart()
		{
			this.ServerStart(this.Port);
		}

		/// <summary>
		/// 服务器关闭的时候需要做的事情<br />
		/// Things to do when the server is down
		/// </summary>
		// Token: 0x06001BA0 RID: 7072 RVA: 0x00009AA1 File Offset: 0x00007CA1
		protected virtual void CloseAction()
		{
		}

		/// <summary>
		/// 关闭服务器的引擎<br />
		/// Shut down the server's engine
		/// </summary>
		// Token: 0x06001BA1 RID: 7073 RVA: 0x00089474 File Offset: 0x00087674
		public virtual void ServerClose()
		{
			bool isStarted = this.IsStarted;
			if (isStarted)
			{
				this.IsStarted = false;
				this.CloseAction();
				Socket coreSocket = this.CoreSocket;
				if (coreSocket != null)
				{
					coreSocket.Close();
				}
				ILogNet logNet = base.LogNet;
				if (logNet != null)
				{
					logNet.WriteInfo(this.ToString(), StringResources.Language.NetEngineClose);
				}
			}
		}

		/// <summary>
		/// 创建一个指定的异形客户端连接，使用Hsl协议来发送注册包<br />
		/// Create a specified profiled client connection and use the Hsl protocol to send registration packets
		/// </summary>
		/// <param name="ipAddress">Ip地址</param>
		/// <param name="port">端口号</param>
		/// <param name="dtuId">设备唯一ID号，最长11</param>
		/// <returns>是否成功连接</returns>
		// Token: 0x06001BA2 RID: 7074 RVA: 0x000894D4 File Offset: 0x000876D4
		public OperateResult ConnectHslAlientClient(string ipAddress, int port, string dtuId)
		{
			bool flag = dtuId.Length > 11;
			if (flag)
			{
				dtuId = dtuId.Substring(11);
			}
			byte[] array = new byte[28];
			array[0] = 72;
			array[1] = 115;
			array[2] = 110;
			array[3] = 0;
			array[4] = 23;
			Encoding.ASCII.GetBytes(dtuId).CopyTo(array, 5);
			OperateResult<Socket> operateResult = base.CreateSocketAndConnect(ipAddress, port, 10000);
			bool flag2 = !operateResult.IsSuccess;
			OperateResult result;
			if (flag2)
			{
				result = operateResult;
			}
			else
			{
				OperateResult operateResult2 = base.Send(operateResult.Content, array);
				bool flag3 = !operateResult2.IsSuccess;
				if (flag3)
				{
					result = operateResult2;
				}
				else
				{
					OperateResult<byte[]> operateResult3 = base.ReceiveByMessage(operateResult.Content, 10000, new AlienMessage(), null);
					bool flag4 = !operateResult3.IsSuccess;
					if (flag4)
					{
						result = operateResult3;
					}
					else
					{
						switch (operateResult3.Content[5])
						{
						case 1:
						{
							Socket content = operateResult.Content;
							if (content != null)
							{
								content.Close();
							}
							result = new OperateResult(StringResources.Language.DeviceCurrentIsLoginRepeat);
							break;
						}
						case 2:
						{
							Socket content2 = operateResult.Content;
							if (content2 != null)
							{
								content2.Close();
							}
							result = new OperateResult(StringResources.Language.DeviceCurrentIsLoginForbidden);
							break;
						}
						case 3:
						{
							Socket content3 = operateResult.Content;
							if (content3 != null)
							{
								content3.Close();
							}
							result = new OperateResult(StringResources.Language.PasswordCheckFailed);
							break;
						}
						default:
							this.ThreadPoolLogin(operateResult.Content);
							result = OperateResult.CreateSuccessResult();
							break;
						}
					}
				}
			}
			return result;
		}

		/// <inheritdoc cref="M:HslCommunication.Core.Net.NetworkServerBase.ConnectHslAlientClient(System.String,System.Int32,System.String)" />
		// Token: 0x06001BA3 RID: 7075 RVA: 0x00089658 File Offset: 0x00087858
		[DebuggerStepThrough]
		public Task<OperateResult> ConnectHslAlientClientAsync(string ipAddress, int port, string dtuId)
		{
			NetworkServerBase.<ConnectHslAlientClientAsync>d__19 <ConnectHslAlientClientAsync>d__ = new NetworkServerBase.<ConnectHslAlientClientAsync>d__19();
			<ConnectHslAlientClientAsync>d__.<>t__builder = AsyncTaskMethodBuilder<OperateResult>.Create();
			<ConnectHslAlientClientAsync>d__.<>4__this = this;
			<ConnectHslAlientClientAsync>d__.ipAddress = ipAddress;
			<ConnectHslAlientClientAsync>d__.port = port;
			<ConnectHslAlientClientAsync>d__.dtuId = dtuId;
			<ConnectHslAlientClientAsync>d__.<>1__state = -1;
			<ConnectHslAlientClientAsync>d__.<>t__builder.Start<NetworkServerBase.<ConnectHslAlientClientAsync>d__19>(ref <ConnectHslAlientClientAsync>d__);
			return <ConnectHslAlientClientAsync>d__.<>t__builder.Task;
		}

		/// <inheritdoc />
		// Token: 0x06001BA4 RID: 7076 RVA: 0x000896B1 File Offset: 0x000878B1
		public override string ToString()
		{
			return string.Format("NetworkServerBase[{0}]", this.Port);
		}
	}
}
